package com.ryan.mdp.json;

import java.io.IOException;
import java.util.Iterator;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.JsonToken;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.deser.std.StdDeserializer;
import org.springframework.remoting.support.RemoteInvocation;
import org.springframework.util.ClassUtils;

public class RemoteInvocationDeserializer extends StdDeserializer<RemoteInvocation> {

    protected RemoteInvocationDeserializer(Class<RemoteInvocation> vc) {
        super(vc);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
    public RemoteInvocation deserialize(JsonParser jp, DeserializationContext context) throws IOException,
            JsonProcessingException {
        RemoteInvocation deserialier = new RemoteInvocation();
        JsonNode jsonNode = jp.readValueAsTree();
        String methodName = jsonNode.findValue("methodName").getTextValue();
        deserialier.setMethodName(methodName);
        
        try {
            JsonNode params = jsonNode.findValue("parameterTypes");
            Class[] types = new Class[params.size()];
            int i=0;
            for (Iterator iterator = params.iterator(); iterator.hasNext();i++) {
                JsonNode type = (JsonNode) iterator.next();
                if (type.asToken() == JsonToken.VALUE_STRING) {
                    types[i]=ClassUtils.forName(type.asText());
                }
            }
            deserialier.setParameterTypes(types);
            
            Object[] args = new Object[params.size()];
            JsonNode arguments = jsonNode.findValue("arguments");
            ObjectMapper mapper = JsonMessageConverter.getMapper();
            i=0;
            for (Iterator iterator = arguments.iterator(); iterator.hasNext();i++) {
                JsonNode arg = (JsonNode) iterator.next();
                Object value = mapper.readValue(arg, (Class)types[i]);
                args[i] = value;
            }
            deserialier.setArguments(args);
        } catch (ClassNotFoundException e) {
            context.instantiationException(_valueClass, e);
        } catch (LinkageError e) {
            context.instantiationException(_valueClass, e);
        }
        return deserialier;
    }
}
